﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using CartoLab.GeometryLib.Geometries;

namespace CartoLab.GeometryLib.SpatialProvider
{
    public class QuadTreeProvider<T> : IProvider<T> where T : class, IQueryExtent
    {
        private CartoLab.GeometryLib.Index.Quadtree.Quadtree _objects = new CartoLab.GeometryLib.Index.Quadtree.Quadtree();

        #region IProvider<T> Members

        public T[] GetObjectsInEnvelope(Envelope envelope)
        {
            IList list = _objects.Query(envelope);
            List<T> result = new List<T>();
            foreach (object o in list)
            {
                T t = o as T;
                if (t != null)
                {
                    if (envelope.Geometry.Intersects(t.Shape))
                        result.Add(t);
                }
            }
            return result.ToArray();
        }
        //public T[] GetObjectsEnvelopeIntersect(Envelope envolop)
        //{
        //    IList list = _objects.Query(envolop);
        //    List<T> result = new List<T>();
        //    foreach (object o in list)
        //    {
        //        T t = o as T;
        //        if (t != null)
        //            result.Add(t);
        //    }
        //    return result.ToArray();
        //}
        public bool OnGeometryChange(T obj, Envelope oriExtent)
        {
            if (obj != null && oriExtent != null)
                if (!_objects.Remove(oriExtent, obj))
                    return false;
            if (obj != null && obj.Extent != null)
                _objects.Insert(obj.Extent, obj);
            return true;
        }


        public T[] GetAllOjbect()
        {
            List<T> result = new List<T>();
            IList list = _objects.QueryAll();
            foreach (object o in list)
            {
                T t = o as T;
                if (t != null)
                    result.Add(t);
            }
            return result.ToArray();
        }

        public int GetObjectCount()
        {
            return _objects.Count;
        }

        public Envelope GetExtents()
        {
            T[] allObjecs = GetAllOjbect();
            Envelope envelop = null;
            foreach (T t in allObjecs)
            {
                if (envelop == null)
                    envelop = t.Extent.Clone();
                else
                    envelop = envelop.Union(t.Extent);
            }
            return envelop;
        }

        public void AddObject(T t)
        {
            _objects.Insert(t.Extent, t);
        }
        public bool DeleteObject(T t)
        {
            return _objects.Remove(t.Extent, t);
        }

        public void RemoveAll()
        {
            _objects = new CartoLab.GeometryLib.Index.Quadtree.Quadtree();
        }

        #endregion
    }

}
